package attr

import (
	"context"
	"gorm.io/gorm"
	"mall/services/product/rpc/internal/mapper"
	"mall/services/product/rpc/internal/mapper/entity"
	"time"

	"mall/services/product/rpc/internal/svc"
	"mall/services/product/rpc/pb"

	"github.com/zeromicro/go-zero/core/logx"
)

type SaveAttrLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewSaveAttrLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SaveAttrLogic {
	return &SaveAttrLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *SaveAttrLogic) SaveAttr(in *pb.SaveAttrDTO) (*pb.SaveAttrVO, error) {
	// 1.mapper
	attrMapper := mapper.NewAttrMapper(l.ctx)
	// 2.builder entity
	builderEntity, categoryEntity := l.builderEntity(in)
	// 3.save db
	attrEntityId, saveErr := l.saveDB(in, attrMapper, builderEntity, categoryEntity)
	if saveErr != nil {
		return nil, saveErr
	}
	// 4.return obj ...
	return &pb.SaveAttrVO{AttrId: attrEntityId}, nil
}

func (l *SaveAttrLogic) saveDB(in *pb.SaveAttrDTO, attrMapper *mapper.AttrMapper,
	builderEntity entity.AttrEntity, categoryEntity entity.AttrCategoryEntity) (int64, error) {

	var attrEntityId int64
	err := l.svcCtx.DBEngin.Transaction(func(tx *gorm.DB) error {
		// 3.1 save attr ...
		attrId, saveAttrErr := attrMapper.InsertCtx(tx, builderEntity)
		if saveAttrErr != nil {
			return saveAttrErr
		}
		// 3.2 save attr category...
		categoryEntity.AttrId = attrId
		categoryMapper := mapper.NewAttrCategoryMapper(l.ctx)
		_, saveAttrCategoryErr := categoryMapper.InsertCtx(tx, categoryEntity)
		if saveAttrCategoryErr != nil {
			return saveAttrCategoryErr
		}
		// 3.3 save attr value ...
		attrValueArr := in.AttrValueArr
		attrEntityId = attrId
		if len(attrValueArr) <= 0 {
			return nil
		}
		var valArr []*entity.AttrValueEntity
		for _, v := range attrValueArr {
			valueEntity := &entity.AttrValueEntity{}
			valueEntity.AttrId = attrId
			valueEntity.Value = v.Value
			valueEntity.UpdateTime = time.Now()
			valueEntity.CreateTime = time.Now()
			valArr = append(valArr, valueEntity)
		}
		valueMapper := mapper.NewAttrValueMapper(l.ctx)
		insertAttrValueErr := valueMapper.BatchInsertCtx(l.svcCtx.DBEngin, valArr)
		if insertAttrValueErr != nil {
			return insertAttrValueErr
		}
		return nil
	})
	if err != nil {
		return -1, err
	}
	return attrEntityId, nil
}

func (l *SaveAttrLogic) builderEntity(in *pb.SaveAttrDTO) (entity.AttrEntity, entity.AttrCategoryEntity) {
	now := time.Now()
	attrEntity := entity.AttrEntity{
		CreateTime: now,
		UpdateTime: now,
		ShopId:     in.ShopId,
		Name:       in.Name,
		Desc:       in.Desc,
		SearchType: int64(in.SearchType),
		AttrType:   int64(in.AttrType),
	}
	categoryEntity := entity.AttrCategoryEntity{
		CategoryId: in.CategoryId,
		CreateTime: now,
		UpdateTime: now,
	}
	return attrEntity, categoryEntity
}
